#include <fstream>
#include <boost/filesystem/path.hpp>
#include <iostream>
#include <string>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <boost/lexical_cast.hpp>
#include "components/CmdLine/cmdargs.h"
#include <boost/regex.hpp>
#include "get_arg.h"
using std::string;
using std::ofstream;
using std::ifstream;
using std::cerr;
using std::cout;
using std::max;
using boost::lexical_cast;





//_______________________________________________________________________________________

//		GetArguments

//				from command line
//				Created [9/13/2001]

//_______________________________________________________________________________________
bool GetArguments(int argc, char* argv[], t_program_args& args)
{
	// optional help directive
	CmdArgUsage opt_help('h', "help", 	"display this message", &cout);

	// required options
	const unsigned REQUIRED = CmdArg::isREQ | CmdArg::isVALREQ;
	CmdArgStr opt_dbname('d', "dbname", "<string>",
								"PostgreSQL database name. ", REQUIRED);
	CmdArgStr opt_host	('h', "host", "<string>",
								"PostgreSQL database host computer address. ");
	CmdArgStr opt_user	('u', "user", "<string>",
								"PostgreSQL database user name. Defaults to 'postgres'.");
	CmdArgStr opt_password('p', "password", "<string>",
								"PostgreSQL database password.");
	CmdArgStr opt_login('l', "login", "<string>",
								"Other PostgreSQL login parameters in the form of "
								"keyword = value. E.g \"port=1234\"");
	
	
	CmdArgStr opt_output_file ('o', "output", "<string>",
								"file for storing results in tab delimited format.", REQUIRED);
	CmdArgInt opt_first_cluster('b', "begin", "<number>",
								"Begin processing clusters from this ID.");
	CmdArgInt opt_last_cluster('s', "stop", "<number>",
								"Stop processing clusters from this ID.");
	CmdArgSet opt_verbose('v', "verbose",
								"issue lots more messages.");
	CmdArgStr opt_err_log ('e', "err_log", "<string>",
								"file for logging bl2seq failures "
								"(defaults to STDERR).");

	string exe_file_name =  boost::filesystem::path(*argv).leaf();
	
	opt_first_cluster = -9999;
	opt_last_cluster = -9999;
		


		// construct command line
	CmdLine  cmdline(exe_file_name.c_str(),
							&opt_first_cluster,
							&opt_last_cluster,
							&opt_dbname,
							&opt_host,
							&opt_user,
							&opt_password,
							&opt_login,
							&opt_output_file,
							&opt_err_log,
							&opt_help,
							&opt_verbose,
							0);

	// parse command line
	CmdArgvIter  argv_iter(--argc, ++argv);
	cmdline.description( "This program calculates KaKs for all members of a gene cluster.");
	if (cmdline.parse(argv_iter))
		return false;

	// make sure the error log file is valid
	string err_log			= opt_err_log.str();
	args.log_to_file		= err_log.length();
	if (args.log_to_file)
	{
		args.f_err_log.open(err_log.c_str(), std::ios_base::out | std::ios_base::ate);
		if (!args.f_err_log.good())
		{
			cerr << "ERROR!! Could not open the error log file (" << err_log << ").\n";
			return(false);
		}
	}
	
	// make sure the output file is valid
	string output_file		= opt_output_file.str();
	args.output_file		= output_file.length();
	args.f_output_file.open(output_file.c_str(), std::ios_base::out | std::ios_base::ate);
	if (!args.f_output_file.good())
	{
		cerr << "ERROR!! Could not open the results output file (" << output_file << ").\n";
		return(false);
	}

	// define verbose first before any error messages generated
	args.verbose	= opt_verbose;


	// initialize postgresql login
	args.db_login = "dbname=" +opt_dbname.str();
	
	string user		= opt_user;
	if (opt_user.str().length())
		args.db_login += " user=" + opt_user.str();
	else
		args.db_login += " user=postgres";
	
	if (opt_host.str().length())
		args.db_login += " host=" + opt_host.str();
	
	if (opt_password.str().length())
		args.db_login += " password=" + opt_password.str();

	if (opt_login.str().length())
		args.db_login += ' ' + opt_login.str();
	
	
	
	int first = opt_first_cluster;
	args.first_cluster = (unsigned)max(0, first);
	int last = opt_last_cluster;
	if (last < 0)
		last = 100000000;
	args.last_cluster = (unsigned)last;
	return true;
}

